﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;

namespace com.core.database
{
    public class GenericBusiness : DataBusiness
    {
        #region Enums
        
        public enum ControlType
        {
            None,
            RadioButton,
            TextBox,
            TextArea,
            Label,
            Literal,
            DropdownList,
            CheckBoxList,
            RadioButtonList,
            ListBox,
            CheckBox,
            GridView
        }
        public enum DataType
        {
            Int,
            Byte,
            Decimal,
            Money,
            String,
            Guid,
            DateTime,
            Date
        }
        public enum Operator
        {
            Equal,
            NotEqual,
            Less,
            LessOrEqual,
            Greater,
            GreaterOrEqual,
            In,
            NotIn,
            Between
        }
        #endregion
        #region Internal Classes
        
        /*
<item name="[Table_Name]" keyField="[Primary Key]" displayField="[Display Column]">
    <field column="[DB_Column_Name]" display="[Display Name]" type="[Data Type]" input="[Input Control]" validator="[Validator Rule]" data="[Input Data]"/>
</item>
        */
        public class ItemType
        {
            public string TypeName { get; set; }
            
            public string KeyField { get; set; }
            public string DisplayField { get; set; }
            public ItemTypeSchemaCollection Schemas { get; set; }
            public static ItemType LoadType(string typeName)
            {
                if (typeName != null)
                {
                    XmlDocument doc = new XmlDocument();
                    doc.Load(@"D:\MDBlue\Company\DatXanh\DX Code\config.xml");
                    XmlNodeList itemNodes = doc.SelectNodes(string.Format("schemas/item[@name = '{0}']", typeName));

                    if (itemNodes != null)
                    {
                        // populate item type
                        ItemType itemType = new ItemType();
                        itemType.TypeName = itemNodes[0].Attributes["name"].Value;
                        itemType.KeyField = itemNodes[0].Attributes["keyField"].Value;
                        itemType.DisplayField = itemNodes[0].Attributes["displayField"].Value;

                        XmlNodeList fieldList = itemNodes[0].ChildNodes;
                        itemType.Schemas = new ItemTypeSchemaCollection();
                        foreach (XmlNode field in fieldList)
                        {
                            ItemTypeSchema schema = new ItemTypeSchema();
                            if (field.Attributes["column"] != null) { schema.Column = field.Attributes["column"].Value; }
                            if (field.Attributes["display"] != null) { schema.Display = field.Attributes["display"].Value; }

                            if (field.Attributes["type"] != null) { schema.DataType = (DataType)Enum.Parse(typeof(DataType), field.Attributes["type"].Value, true); }
                            if (field.Attributes["input"] != null) { schema.InputControl = (ControlType)Enum.Parse(typeof(ControlType), field.Attributes["input"].Value, true); }
                            if (field.Attributes["validator"] != null) { schema.Validator = field.Attributes["validator"].Value; }
                            if (field.Attributes["data"] != null) { schema.Data = field.Attributes["data"].Value; }
                            itemType.Schemas.Add(schema);
                        }
                        return itemType;
                    }
                }
                return null;
            }
        }
        public class ItemTypeSchemaCollection : List<ItemTypeSchema>
        {
            public ItemTypeSchema this[string property]
            {
                get
                {
                    return this.FirstOrDefault(obj => obj.Column == property);
                }
            }
        }
        public class ItemTypeSchema
        {
            public string Column { get; set; }
            public string Display { get; set; }
            public DataType DataType { get; set; }
            public ControlType InputControl { get; set; }
            public string FormatData { get; set; }
            public string Validator { get; set; }
            public string Data { get; set; }

        }
        public class ItemFilter
        {
            public ItemTypeSchema Property { get; set; }
            public Operator Operator { get; set; }
            public object Value { get; set; }
            public string BuildFilter()//
            {
                //more core here
                return "";
            }
        }
        public class ItemOrder
        {
            public ItemTypeSchema Property { get; set; }
            public bool IsDesc { get; set; }
            public string BuildOrder()
            {
                return Property.Column + (IsDesc ? " desc" : " asc");

            }
        }
        #endregion
        public bool InsertItem(ItemType type, DataItem item)
        {
            string query = "INSERT INTO {0} ({1}) VALUES ({2})";
            string columns = string.Empty;
            string table = type.TypeName;
            string values = string.Empty;
            int itemCount = item.Keys.Count();
            for (int i = 0; i < itemCount; i++)
            {
                string value = item[item.Keys[i]].ToString();
                switch (type.Schemas[item.Keys[i]].DataType)
                {
                    case DataType.String:
                    case DataType.Guid:
                    case DataType.Date:
                    case DataType.DateTime:
                        value = "'" + value + "'";
                        break;
                }
                columns += item.Keys[i] + ",";
                values +=  value + ",";
            }
            columns = columns.TrimEnd(',');
            values = values.TrimEnd(',');
            query = string.Format(query, table, columns, values);
            return this.Agent.ExecuteNonQuery(query) > 0? true : false;
            //item[""]
        }
        public bool UpdateItem(ItemType type, DataItem item)
        {
            //Where condition based on type.KeyField
            string query = "UPDATE {0} SET {1} WHERE {2}";
            string set = string.Empty;
            string from = type.TypeName;
            string where = type.KeyField + " = " + item[type.KeyField];
            int itemCount = item.Keys.Count();
            for (int i = 0; i < itemCount; i++)
            {
                if (item.Keys[i].ToString() == type.KeyField)
                {
                    continue;
                }
                    string value = item[item.Keys[i]].ToString();
                    switch (type.Schemas[item.Keys[i]].DataType)
                    {
                        case DataType.String:
                        case DataType.Guid:
                        case DataType.Date:
                        case DataType.DateTime:
                            value = "'" + value + "'";
                            break;
                    }
                    set += item.Keys[i] + " = " + value + ",";
            }
            set = set.TrimEnd(',');
            query = string.Format(query, from, set, where);
            return this.Agent.ExecuteNonQuery(query) > 0 ? true: false;
        }
        public bool DeleteItem(ItemType type, object itemId)
        {
            string query = "DELETE FROM {0} WHERE {1}";
            string from = type.TypeName;
            string where = type.KeyField + " = " + itemId.ToString();
            query = string.Format(query, from, where);
            return this.Agent.ExecuteNonQuery(query) > 0 ? true : false;
        }
        public DataItem GetItem(ItemType type, object itemId)
        {
            string query = "SELECT {0} FROM {1} WHERE {2}";
            string select = string.Empty;
            string from = type.TypeName;
            string where = type.KeyField + " = " + itemId.ToString();
            foreach (ItemTypeSchema schema in type.Schemas)
            {
                select += schema.Column + ",";
            }
            select = select.TrimEnd(',');
            query = string.Format(query, select, from, where);
            DataItem[] items = this.Agent.ExecuteQuery(query);
            if (items != null)
            {
                return items[0];
            }
            return null;
        }
        public DataItem[] GetItems(ItemType type, IEnumerable<ItemFilter> filters, IEnumerable<ItemOrder> orders, int pageIndex, int pageSize, ref int count)
        {
            return null;
        }
    }
}
